#pragma once

#include <QObject>
#include <gp_Pnt.hxx>
#include <set>
#include <vtkActor.h>
#include <vtkSmartPointer.h>
#include <Standard_Handle.hxx>
#include <TopoDS_Edge.hxx>
#include <Topods_Wire.hxx>
#include <TopoDS_Face.hxx>
#include <IVtk_Types.hxx>

enum class ESketchCurveType : uint8_t
{
	Line,
	Circle,
	ArcCircle,
	Rectangle,
};

enum class ESketchActionState : uint8_t
{
    None,
    CreateCurve,
    TrimCurve,
    ExtendCurve
};

class MainWindow;
class QSketch;
class QSketchCurveAction;
enum class EVertexType : unsigned char;
class QAction;
class QIVtkSelectionPipeline;
class SketchOperation;
class vtkActor;

class QSketchManager  : public QObject
{
	Q_OBJECT

public:
	QSketchManager(MainWindow* mainWindow);
	~QSketchManager();

	void OnMouseMove(Standard_Integer theX, Standard_Integer theY);
	void OnLeftButtonDown();
	void PickActor(vtkActor* actor);

	// 创建一个草图
	void CreateSketch(const gp_Pnt& O, const gp_Dir& N, const gp_Dir& Right);
	// 创建草图
	void CreateSketchByOperation(SketchOperation* op);
	// 完成草图创建
	void FinishCreateSketch();
	// 开始创建草图曲线
	void CreateSketchCurve(ESketchCurveType curveType);
	// 结束创建草图曲线
	void EndCreateSketchCurve(Handle(QIVtkSelectionPipeline) createActor);
	// 改变点可选择类型
	void filterSelectVertexType(EVertexType type, QAction* action);
	// 获得当前草图的法向量
	gp_Dir GetCurrentNormal();
	// 获得当前草图
	QSketch* GetCurrentSketch() { return m_currentSketch; }
	// 获得edge当前草图的交点
	void HandleEdgeIntersections(Handle(QIVtkSelectionPipeline) actor);
	// 修剪曲线
	void TrimCurve();
	// 延伸曲线
	void ExtendCurve();
	// 清理未完成action状态
	void ClearActionState();
	void redo();
	void undo();

	// 给定义原点O、法向量N、右向量Right，创建一个模型变换矩阵将局部uv坐标转换到世界坐标
	static gp_Trsf GetLocalToGlobalTransform(const gp_Pnt& O, const gp_Dir& N, const gp_Dir& Right);
    static gp_Trsf GetGlobalToLocalTransform(const gp_Pnt& O, const gp_Dir& N, const gp_Dir& Right);
	// 处理边，提取出闭合edge转化为wire
	static std::tuple<std::vector<TopoDS_Wire>, std::vector<TopoDS_Edge>> PreprocessEdges(const std::vector<TopoDS_Edge>& edges);
	// 将一组edge转化为wire
	static std::vector<TopoDS_Wire> BuildWiresFromEdges(const std::vector<TopoDS_Edge>& edges);
	// 修复wire的方向
	static TopoDS_Wire FixWireOrientation(TopoDS_Wire& wire, bool isOuter);
	// 判断wire是否为顺时针
	static bool IsWireClockwise(const TopoDS_Wire& wire);
	// 判断线框 inner 是否在 outer 内部：
	static bool IsWireInside(const TopoDS_Wire& outer, const TopoDS_Wire& inner);
	// 找到最外层wire
	static TopoDS_Wire FindOuterWire(std::vector<TopoDS_Wire>& wires);
	// 将wire组合形成face，外圈形成基本面，内圈形成孔
	static TopoDS_Face CreateFaceWithHoles(std::vector<TopoDS_Wire>& wires);

protected:
	// 获得选择的TopoDS_Edge
	TopoDS_Edge GetSelectedEdge();
	// 延长直线
	TopoDS_Edge ExtendEdge(const TopoDS_Edge& edge, float scale = 5.f);
	// 获得圆弧的完整圆
	TopoDS_Edge GetArcBasic(const TopoDS_Edge& edge);
public:
	// 草图所有点
	std::unordered_map<EVertexType, std::vector<gp_Pnt>> m_points;

protected:
	MainWindow* m_mainWindow;

	// 当前激活的草图
	QSketch* m_currentSketch;

	// 当前曲线action
	QSketchCurveAction* m_currentCurveAction;

	// 曲线action用于创建不同的曲线
	std::unordered_map<ESketchCurveType, QSketchCurveAction*> m_curveActions;

	// 所有草图
	std::vector<QSketch*> m_sketchs;

	// 当前屏幕交点
	gp_Pnt m_currentIntersectionPoint;

	// 可选点类型
	std::set<EVertexType> _selectedVertexTypes;

	// 用于显示捕获点的小球
	vtkSmartPointer<vtkActor> tempSphereActor;

	// 存储与pipeline相关联的交点
    std::unordered_map<IVtk_IdType, std::vector<gp_Pnt>> m_pipelineIntersectionPoints;

	// 当前草图操作状态
	ESketchActionState m_curActionState = ESketchActionState::None;

	// 修剪曲线对象
	Handle(QIVtkSelectionPipeline) m_actionCurveActor;
};
